package com.sunday.common.http.apache;

import com.sunday.common.core.asserts.BusinessAssert;
import com.sunday.common.core.constants.LogConstants;
import com.sunday.common.core.enums.ErrorCodeEnum;
import com.sunday.common.core.enums.HttpExpandStatusEnum;
import com.sunday.common.core.gson.GsonUtils;
import com.sunday.common.core.remoting.base.response.ExceptionResponse;
import com.sunday.common.core.remoting.base.response.Response;
import com.sunday.common.core.remoting.base.response.ResponseHandler;
import com.sunday.common.core.remoting.base.response.core.MethodCallback;
import com.sunday.common.core.remoting.base.response.core.ThrowableFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.core5.http.HttpStatus;
import org.springframework.lang.Nullable;

/**
 * HTTP 响应处理
 *
 * @author zsy
 * @since 2022/10/15
 */
@Slf4j
public class HttpResponseHandler {

    public static <K> Response<K> invoke(MethodCallback<HttpResult> callback) {
        return invoke(callback, true, null, null);
    }

    public static <K> Response<K> invoke(MethodCallback<HttpResult> callback, @Nullable Class<K> bodyClass) {
        return invoke(callback, true, bodyClass, null);
    }

    public static <K> Response<K> invoke(MethodCallback<HttpResult> callback, boolean showLog, @Nullable Class<K> bodyClass) {
        return invoke(callback, showLog, bodyClass, null);
    }

    public static <K> Response<K> invoke(MethodCallback<HttpResult> callback, @Nullable Class<K> bodyClass, @Nullable ThrowableFilter filter) {
        return invoke(callback, true, bodyClass, filter);
    }

    public static <K> Response<K> invoke(MethodCallback<HttpResult> callback, boolean showLog, @Nullable Class<K> bodyClass, @Nullable ThrowableFilter filter) {
        return ResponseHandler.invoke(() -> {
            HttpResult httpResult = callback.doWith();
            if (showLog) {
                log.info(LogConstants.http_response_format, httpResult);
            }
            /**
             * 触发sentinel
             */
            if (HttpExpandStatusEnum.CIRCUIT_BREAK.code == httpResult.getCode()) {
                return Response.error(ErrorCodeEnum.B0_210, HttpExpandStatusEnum.CIRCUIT_BREAK.toJson(), true);
            }
            BusinessAssert.isTrue(HttpStatus.SC_OK == httpResult.getCode(), ErrorCodeEnum.C0_100, () -> "HTTP响应状态码异常");
            if (bodyClass == null) {
                return Response.ok(httpResult.getContent());
            }
            return Response.ok(GsonUtils.DEFAULT.fromJson(httpResult.getContent(), bodyClass));
        }, ExceptionResponse.HTTP_RESPONSE_RESOLVE, filter);
    }

}
